这些方法,能够让你的Python程序快如闪电 | 您所在的位置:网站首页 › python real怎么用 › 这些方法,能够让你的Python程序快如闪电 |
作者:Martin Heinz 机器之心编译 参与:郭元晨、魔王 本文将介绍如何提升 Python 程序的效率,让它们运行飞快! 讨厌 Python 的人总是会说,他们不想用 Python 的一个重要原因是 Python 很慢。而事实上,无论使用什么编程语言,特定程序的运行速度很大程度上取决于编写程序的开发人员以及他们优化程序、加快程序运行速度的技能。 那么,让我们证明那些人错了!本文将介绍如何提升 Python 程序的效率,让它们运行飞快! ![]() ![]() 计时与性能分析 在开始优化之前,我们首先需要找到代码的哪一部分真正拖慢了整个程序。有时程序性能的瓶颈显而易见,但当你不知道瓶颈在何处时,这里有一些帮助找到性能瓶颈的办法: 注:下列程序用作演示目的,该程序计算 e 的 X 次方(摘自 Python 文档): # slow_program.py from decimal import * defexp(x): getcontext().prec += 2 i, lasts, s, fact, num = 0, 0, 1, 1, 1 while s != lasts: lasts = s i += 1 fact *= i num *= x s += num / fact getcontext().prec -= 2 return +s exp(Decimal(150)) exp(Decimal(400)) exp(Decimal(3000)) 最懒惰的「性能分析」 首先,最简单但说实话也很懒的方法——使用 Unix 的 time 命令: ~ $ time python3.8 slow_program.py real0m11,058s user 0m11,050s sys 0m0,008s 如果你只想给整个程序计时,这个命令即可完成目的,但通常是不够的…… 最细致的性能分析 另一个极端是 cProfile,它提供了「太多」的信息: ~ $ python3.8 -m cProfile -s time slow_program.py 1297functioncalls(1272 primitive calls)in11.081 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 311.0793.69311.0793.693 slow_program.py:4(exp) 10.0000.0000.0020.002 {built-in method _imp.create_dynamic} 4/10.0000.00011.08111.081 {built-in method builtins.exec} 60.0000.0000.0000.000 {built-in method __new__ of type object at 0x9d12c0} 60.0000.0000.0000.000 abc.py:132(__new__) 230.0000.0000.0000.000 _weakrefset.py:36(__init__) 2450.0000.0000.0000.000 {built-in method builtins.getattr} 20.0000.0000.0000.000 {built-in method marshal.loads} 100.0000.0000.0000.000 :1233(find_spec) 8/40.0000.0000.0000.000 abc.py:196(__subclasscheck__) 150.0000.0000.0000.000 {built-in method posix.stat} 60.0000.0000.0000.000 {built-in method builtins.__build_class__} 10.0000.0000.0000.000 __init__.py:357(namedtuple) 480.0000.0000.0000.000 :57(_path_join) 480.0000.0000.0000.000 :59() 10.0000.00011.08111.081 slow_program.py:1() ... 这里,我们结合 cProfile 模块和 time 参数运行测试脚本,使输出行按照内部时间(cumtime)排序。这给我们提供了大量信息,上面你看到的行只是实际输出的 10%。从输出结果我们可以看到 exp 函数是罪魁祸首(惊不惊喜,意不意外),现在我们可以更加专注于计时和性能分析了…… 计时专用函数 现在我们知道了需要关注哪里,那么我们可能只想要给运行缓慢的函数计时而不去管代码的其他部分。我们可以使用一个简单的装饰器来做到这点: deftimeit_wrapper(func): @wraps(func) defwrapper(*args, **kwargs): start = time.perf_counter() # Alternatively, you can use time.process_time() func_return_val = func(*args, **kwargs) end = time.perf_counter() print('{0: |
CopyRight 2018-2019 实验室设备网 版权所有 |